package com.isyscore.cse.sdk

import com.isyscore.kotlin.common.isMac
import com.isyscore.kotlin.common.isWindows
import java.io.File
import java.io.FileNotFoundException

object CrossScriptEngine {

    val ISC = when {
        isWindows -> "C:\\Windows\\System32\\isc.exe"
        isMac -> "/usr/local/bin/isc"
        else -> "/usr/bin/isc"
    }
    val ISCC = when {
        isWindows -> "C:\\Windows\\System32\\iscc.exe"
        isMac -> "/usr/local/bin/iscc"
        else -> "/usr/bin/iscc"
    }

    /**
     * 原生插件的加载路径
     */
    @JvmStatic
    var nativePluginPath = "."

    /**
     * 初始化 SDK，在使用 SDK 内功能前，必须先进行初始化
     *
     * Mac/Linux: 部署 Pod 时，设置 LD_LIBRARY_PATH 为包含 libcrossscript.so 的路径，或将 libcrossscript.so 拷贝到 /usr/lib 内
     * Windows:
     */
    @JvmStatic
    fun initSDK() {
        if (!File(ISC).exists()) {
            throw FileNotFoundException("$ISC not found.")
        }
        if (!File(ISCC).exists()) {
            throw FileNotFoundException("$ISCC not found.")
        }
        println("CrossScriptEngine: initialized.")
    }

    /**
     * 加载一个未经编译的脚本源码文件
     * @param filePath 文件路径
     * @return 脚本ID
     */
    @JvmStatic
    fun addScriptFile(filePath: String): String = CrossScriptExecutor.executorFile(filePath)

    /**
     * 加载一个脚本源码字符串
     * @param text 源码字符串
     * @return 脚本ID
     */
    @JvmStatic
    fun addScriptText(text: String): String = CrossScriptExecutor.executorText(text)

    /**
     * 加载一个经过编译的脚本文件
     * @param filePath 文件路径
     * @return 脚本ID
     */
    @JvmStatic
    fun addScriptBinary(filePath: String): String = CrossScriptExecutor.executorBinary(filePath)

    /**
     * 添加一个引用路径，该路径指出了脚本代码中的 include/import/uses 相关标记所能够查找的代码目录
     * @param id 脚本ID
     * @param path 引用路径（纯路径，不包含文件名）
     */
    @JvmStatic
    fun setIncludePath(id: String, path: String) {
        scriptMap[id]?.includePath = path
    }

    /**
     * 设置执行超时
     * @param id 脚本ID
     * @param timeout 超时时间(毫秒)
     */
    @JvmStatic
    fun setExecuteTimeout(id: String, timeout: Long = 5000L) {
        scriptMap[id]?.executeTimeout = timeout
    }

    /**
     * 移除脚本
     * @param id 脚本ID
     * @return 是否移除成功
     */
    @JvmStatic
    fun removeScript(id: String): Boolean = scriptMap.remove(id) != null

    /**
     * 执行脚本
     * @param id 脚本ID
     * @return 是否执行成功
     */
    @JvmStatic
    fun runScript(id: String): Boolean = scriptMap[id]?.run() ?: false

    /**
     * 获取脚本的输出(STDOUT)信息，仅当脚本执行成功时可以获取
     * @param id 脚本ID
     * @return 输出信息
     */
    @JvmStatic
    fun getOutputMessage(id: String): String = scriptMap[id]?.outputMessage ?: ""

    /**
     * 获取运行时错误，仅当 runScript 方法返回 false 时可以调用
     * @param id 脚本ID
     * @return 错误信息
     */
    @JvmStatic
    fun getErrorMessage(id: String): String = scriptMap[id]?.errorMessage ?: ""

    /**
     * 编译一个脚本源码文件
     * @param codePath 源码文件路径
     * @param destPath 目标文件路径
     * @param includePath 编译时引用路径，该路径指出了脚本代码中的 include/import/uses 相关标记所能够查找的代码目录
     * @return 是否编译成功
     */
    @JvmStatic
    fun compile(id: String): Pair<Boolean, String> = scriptMap[id]?.compile() ?: (false to "")

}